#include "PNGImageDecoder.h"

void PNGImageDecoder::Decode(FILE *fp, Texture2D &image)
{       

	png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_infop infoPtr = png_create_info_struct(pngPtr);

	png_init_io(pngPtr, fp);
	png_read_info(pngPtr, infoPtr);

	image.width = png_get_image_width(pngPtr, infoPtr);
	image.height = png_get_image_height(pngPtr, infoPtr);

	//bits per CHANNEL! note: not per pixel!
	png_uint_32 bitdepth   = png_get_bit_depth(pngPtr, infoPtr);

	//Number of channels
	image.channels   = png_get_channels(pngPtr, infoPtr);

	//Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc)
	png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr);

	switch (color_type) {
	case PNG_COLOR_TYPE_PALETTE:
		png_set_palette_to_rgb(pngPtr);        
		image.channels = 3;           
		break;
	}

	/*if the image has a transperancy set.. convert it to a full Alpha channel..*/
	if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
		png_set_tRNS_to_alpha(pngPtr);
		image.channels += 1;
	}

	//We don't support 16 bit precision.. so if the image Has 16 bits per channel
	//precision... round it down to 8.
	if (bitdepth == 16)
		png_set_strip_16(pngPtr);    
	image.data = new unsigned char[image.width * image.height * bitdepth * image.channels >> 3];

	const unsigned int stride = image.width * bitdepth * image.channels >> 3;
	png_bytep* rowPtrs = new png_bytep[image.height];

	for (size_t i = 0; i < image.height; i++) {
		size_t q = (i) * stride;
		rowPtrs[i] = (png_bytep) image.data + q;
	}   
	png_read_image(pngPtr, rowPtrs);
	SAFE_DEL_ARRAY(rowPtrs);   

	png_destroy_read_struct(&pngPtr, &infoPtr, NULL);

};
